/**
  * This class is the scanner for the script language.
  */
package scriptrunner.parser;

import java_cup.runtime.*;

%%

%class Lexer
%unicode
%cup
%line
%column

%{
	StringBuffer string = new StringBuffer();

	private Symbol symbol(int type) {
		return new Symbol(type, yyline, yycolumn);
	}

	private Symbol symbol(int type, Object value) {
		return new Symbol(type, yyline, yycolumn, value);
	}
%}

LineTerminator = \r|\n|\r\n
InputCharacter = [^\r\n]
WhiteSpace     = {LineTerminator} | [ \t\f]

/* comments */
Comment = {TraditionalComment} | {EndOfLineComment} | {DocumentationComment}

TraditionalComment   = "/*" [^*] ~"*/" | "/*" "*"+ "/"
EndOfLineComment     = "//" {InputCharacter}* {LineTerminator}
DocumentationComment = "/**" {CommentContent} "*"+ "/"
CommentContent       = ( [^*] | \*+ [^/*] )*

Identifier = [:jletter:] [:jletterdigit:]*
DecIntegerLiteral = 0 | [1-9][0-9]*
DecFloatLiteral = (0 | [1-9][0-9]*)\.[:jletterdigit:]+ 

%state STRING

%%

/* keywords */
<YYINITIAL> "SET"						{ return symbol(sym.SET); }
<YYINITIAL> "RETURN"					{ return symbol(sym.RETURN); }
<YYINITIAL> "IF"						{ return symbol(sym.IF); }
<YYINITIAL> "THEN"					{ return symbol(sym.THEN); }
<YYINITIAL> "ELSE"					{ return symbol(sym.ELSE); }
<YYINITIAL> "END"						{ return symbol(sym.END); }
<YYINITIAL> "FUNC"					{ return symbol(sym.FUNC); }
<YYINITIAL> "HTTP"					{ return symbol(sym.HTTP); }
<YYINITIAL> "WHILE"					{ return symbol(sym.WHILE); }
<YYINITIAL> "DO"					{ return symbol(sym.DO); }

<YYINITIAL> {
  /* identifiers */ 
  {Identifier}							{ return symbol(sym.IDENTIFIER, yytext().toString() ); }
  {DecIntegerLiteral}				{ return symbol(sym.INTEGER_LITERAL, yytext().toString() ); }
  {DecFloatLiteral}					{ return symbol(sym.FLOAT_POINT_LITERAL, yytext().toString() ); }
 
  /* string literals */
  \"										{ string.setLength(0); yybegin(STRING); }

  /* operators */
  "("										{ return symbol(sym.LPAREN); }
  ")"										{ return symbol(sym.RPAREN); }
  "["										{ return symbol(sym.LBRACK); }
  "]"										{ return symbol(sym.RBRACK); }										
  "+"										{ return symbol(sym.PLUS); }
  "-"										{ return symbol(sym.MINUS); }
  "*"										{ return symbol(sym.TIMES); }
  "/"										{ return symbol(sym.DIVIDE); }
  ","										{ return symbol(sym.COMMA); }
  "="										{ return symbol(sym.EQ); }
  "=="									{ return symbol(sym.EQEQ); }
  "!="									{ return symbol(sym.NOTEQ); }
  "<"										{ return symbol(sym.LT); }
  ">"										{ return symbol(sym.GT); }
  "<="									{ return symbol(sym.LTEQ); }
  ">="									{ return symbol(sym.GTEQ); }

  /* comments */
  {Comment}								{ /* ignore */ }
 
  /* whitespace */
  {WhiteSpace}							{ /* ignore */ }
}

<STRING> {
  \"										{ yybegin(YYINITIAL); 
												return symbol(sym.STRING_LITERAL, 
												string.toString()); }
  [^\n\r\"\\]+							{ string.append( yytext() ); }
  \\t										{ string.append('\t'); }
  \\n										{ string.append('\n'); }

  \\r										{ string.append('\r'); }
  \\\"									{ string.append('\"'); }
  \\										{ string.append('\\'); }
}

/* error fallback */
.|\n										{ throw new Error("Illegal character <"+yytext()+">"); }

